package ysu.sxm.ptjc.Service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import ysu.sxm.ptjc.Dao.DefectStatisticsDao;
import ysu.sxm.ptjc.Dao.DefectTopDao;
import ysu.sxm.ptjc.Domin.DateRange;
import ysu.sxm.ptjc.Domin.DefectReq;
import ysu.sxm.ptjc.Domin.DefectTopCondition;
import ysu.sxm.ptjc.Service.DefectStatisticsService;
import ysu.sxm.ptjc.Utill.Utills;
import ysu.sxm.ptjc.pojo.*;

import java.util.*;

@Service
public class DefectStatisticsServiceImpl implements DefectStatisticsService {
    @Autowired
    DefectStatisticsDao defectStatisticsDao;
    @Autowired
    DefectTopDao defectTopDao;
    @Override
    public Map<String,Object> defect(DefectReq defectReq) {
        Map<String,Object> res=new HashMap<>();
        List<Object> defect=new ArrayList<>();
        List<Object> defectScrap=new ArrayList<>();
        if(!defectReq.isNoOtherCondition()){
            List<DateRange> dateRanges=new ArrayList<>();//通过条件查询出订单编号
            dateRanges = getDateRanges(defectReq, dateRanges);//获取日期
            List<String> proNum=defectStatisticsDao.getProduceNum(defectReq);//获取produce_num
            if(proNum!=null&&proNum.size()!=0){
                creatRes(res, defect, dateRanges, proNum, 0, "Rework");
                creatRes(res, defectScrap, dateRanges, proNum, 1, "Scrap");
                Long proTotal=defectTopDao.produceTotal(proNum);
                if (proTotal!=null&&proTotal!=0) {
                    res.put("proTotal",proTotal);
                }else{
                    res.put("proTotal",0);
                }
            }
        }
        return res;
    }
    /**
     * Req:produce_nums&&date--->discrap_id(s)
     *      produce_num->订单编号
     *      i->缺陷等级
     *      type->等级对应的类型
     * Resp:对应类型的不同缺陷的数量
     */
    private void creatRes(Map<String, Object> res, List<Object> defect, List<DateRange> dateRanges, List<String> proNum, int i, String type) {
        List<DefectTypeInfo> defectTypeInfos = defectStatisticsDao.getDiscrapeId(proNum, i, dateRanges);
        if(defectTypeInfos!=null&&defectTypeInfos.size()!=0){
            getDiscrap(defect, defectTypeInfos);
        }
        res.put(type, defect);
    }
    public List<DateRange> getDateRanges(DefectReq defectReq, List<DateRange> dateRanges) {
        if(defectReq.getDay()==null||defectReq.getDay().isEmpty()){
            if(defectReq.getWeek()==null||defectReq.getWeek().isEmpty()){
                if (defectReq.getMonth()!=null&&(!defectReq.getMonth().isEmpty())){
                    dateRanges= Utills.getMonthDays(defectReq.getMonth());
                }
            }else{
                dateRanges=Utills.getWeekDays(defectReq.getWeek());
            }
        }else{
            for (String day:defectReq.getDay()
            ) {
                dateRanges.add(new DateRange(day,day));
            }
        }
        return dateRanges;
    }
    public void getDiscrap(List<Object> defect, List<DefectTypeInfo> defectTypeInfos) {
        defect.add(defectStatisticsDao.getCastingDefect(defectTypeInfos));
        defect.add(defectStatisticsDao.getExtrusionDefectInfo(defectTypeInfos));
        defect.add(defectStatisticsDao.getMachiningDefectsInfo(defectTypeInfos));
        defect.add(defectStatisticsDao.getPolishingDefectInfo(defectTypeInfos));
        defect.add(defectStatisticsDao.getOxidationDefectInfo(defectTypeInfos));
        defect.add(defectStatisticsDao.getAssemblyDefectInfo(defectTypeInfos));
        defect.add(defectStatisticsDao.getCdpDefectInfo(defectTypeInfos));
    }

    @Override
    public String defTop(DefectTopCondition topCondition) {
        DateRange dateRanges=Utills.getMonthDays(topCondition.getMonth());
        List<String> produce_nums=defectTopDao.getProNum(dateRanges);
        Map<String,String> res=new HashMap<>();
        if(produce_nums!=null&&produce_nums.size()!=0){
            Long total=defectTopDao.produceTotal(produce_nums);
            List<DefectTypeInfo> defectTypeInfos=defectTopDao.getDiscrapeId(produce_nums);
            Map<String,List<String>> req=describeToTable(topCondition.getDefectDescribe());
            if (total!=null&&total!=0) {
                CastingDefectsInfo castingDefectsInfo=defectTopDao.getCastingDefect(req.get("casting_defects_info"),defectTypeInfos);
                creatDefectTopMap(res, total, castingDefectsInfo);
                ExtrusionDefectInfo extrusionDefectInfo=defectTopDao.getExtrusionDefectInfo(req.get("extrusion_defect_info"),defectTypeInfos);
                creatDefectTopMap(res, total, extrusionDefectInfo);
                MachiningDefectsInfo machiningDefectsInfo=defectTopDao.getMachiningDefectsInfo(req.get("machining_defects_info"),defectTypeInfos);
                creatDefectTopMap(res, total, machiningDefectsInfo);
                PolishingDefectInfo polishingDefectInfo=defectTopDao.getPolishingDefectInfo(req.get("polishing_defect_info"),defectTypeInfos);
                creatDefectTopMap(res, total, polishingDefectInfo);
                OxidationDefectInfo oxidationDefectInfo=defectTopDao.getOxidationDefectInfo(req.get("oxidation_defect_info"),defectTypeInfos);
                creatDefectTopMap(res, total, oxidationDefectInfo);
                AssemblyDefectInfo assemblyDefectInfo=defectTopDao.getAssemblyDefectInfo(req.get("assembly_defect_info"),defectTypeInfos);
                creatDefectTopMap(res,total,assemblyDefectInfo);
                CdpDefectInfo cdpDefectInfo=defectTopDao.getCdpDefectInfo(req.get("cdp_defect_info"),defectTypeInfos);
                creatDefectTopMap(res,total,cdpDefectInfo);
            }
        }
        return JSON.toJSONString(Utills.topRes(res,topCondition.getValue()));
    }

    private void creatDefectTopMap(Map<String, String> res, long total, Object defectInfo) {
        JSONObject j1= (JSONObject) JSON.toJSON(defectInfo);
        for (Map.Entry j:j1.entrySet()
             ) {
            if (j.getValue()!=null){

                res.put(j.getKey().toString(), Utills.calculation((long)j.getValue(),total));
            }
        }
    }

    /**
     * 关于缺陷描述与缺陷统计表的映射
     */
    private Map<String,List<String>> describeToTable(List<String> describes){
        Map<String,List<String>> res=new HashMap<>();
        for (String describe:describes) {
            switch (describe){
                case "white_line":
                case "spray_pinhole":
                case "colour_aberration":
                    if (!res.containsKey("casting_defects_info")){
                        List<String> cdi=new ArrayList<>();
                        cdi.add(describe);
                        res.put("casting_defects_info",cdi);
                    }else{
                        res.get("casting_defects_info").add(describe);
                    }
                    break;
                case "black_line":
                case "slag_inclusion":
                case "profile_groove":
                case "watermark_extrusion":
                case "wave_print":
                case "pitting":
                    if(!res.containsKey("extrusion_defect_info")){
                        List<String> edi=new ArrayList<>();
                        edi.add(describe);
                        res.put("extrusion_defect_info",edi);
                    }else{
                        res.get("extrusion_defect_info").add(describe);
                    }
                    break;
                case "size_defect":
                case "thorn_broken":
                case "end_pit":
                case "white_mark":
                case "pit_or_bag":
                case "out_of_shape":
                case "missed_process":
                case "lack_meat":
                case "extra_meat":
                case "grinding_mark":
                case "fish_tail":
                case "other":
                    if(!res.containsKey("machining_defects_info")){
                        List<String> mdi=new ArrayList<>();
                        mdi.add(describe);
                        res.put("machining_defects_info",mdi);
                    }else{
                        res.get("machining_defects_info").add(describe);
                    }
                    break;
                case "polished_grain":
                case "polish_broken":
                case "nothrow_clean":
                case "residual":
                case "polishing_groove":
                case "orange_surface":
                    if(!res.containsKey("polishing_defect_info")){
                        List<String> pdi=new ArrayList<>();
                        pdi.add(describe);
                        res.put("polishing_defect_info",pdi);
                    }else{
                        res.get("polishing_defect_info").add(describe);
                    }
                    break;
                case "scratch":
                case "burn_broken":
                case "disordered_surface":
                case "glove_print":
                case "furroad_broken":
                case "clip_print":
                case "thick_surface":
                case "highlights":
                case "electric_shock":
                case "rainbow_broken":
                case "white_fog":
                case "watermark":
                case "paint_spot":
                case "grain_broken":
                case "cleft_membrane":
                case "lacquer_bubble":
                    if(!res.containsKey("oxidation_defect_info")){
                        List<String> odi=new ArrayList<>();
                        odi.add(describe);
                        res.put("oxidation_defect_info",odi);
                    }else{
                        res.get("oxidation_defect_info").add(describe);
                    }
                    break;
                case "turnover_scratch":
                    if(!res.containsKey("assembly_defect_info")){
                        List<String> adi=new ArrayList<>();
                        adi.add(describe);
                        res.put("assembly_defect_info",adi);
                    }else{
                        res.get("assembly_defect_info").add(describe);
                    }
                    break;
                case "broken_surface":
                case "impurity":
                case "sanding":
                case "poor_corrosion":
                case "corrosion_point":
                case "threshold_broken":
                case "deviation":
                    //cdp_defect_info
                    if(!res.containsKey("cdp_defect_info")){
                        List<String> cdpdi=new ArrayList<>();
                        cdpdi.add(describe);
                        res.put("cdp_defect_info",cdpdi);
                    }else{
                        res.get("cdp_defect_info").add(describe);
                    }
                    break;
                default:
                    break;
            }
        }
        return res;
    }
}
